#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
using namespace std;

#ifdef LOCAL
	#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
	#define eprintf(...) 42
#endif

int bit(int mask, int i)
{
	return ( (mask >> i) & 1);
}

const int maxn = (int) 1e5;

struct Node
{
	int par;
	int pos, len;
	int linkMask;
	map <char, int> go, link;

	Node() : par(), pos(), len(), linkMask(), go(), link() {}
	Node(int _par, int _pos, int _len) : par(_par), pos(_pos), len(_len), linkMask(), go(), link() {}
};

Node tree[2 * maxn];
const int ALP = 30;
int sz, root;

void init()
{
	tree[0] = Node();
	tree[0].linkMask = (1 << ALP) - 1;
	for (int i = 0; i < ALP; i++)
		tree[0].link[i] = 1;
	
	tree[1] = Node(0, -1, 1);
	sz = 2;
	root = 1;
}

char str[maxn];

void addLink(int v, int to, char c)
{
	tree[v].link[c] = to;
	tree[v].linkMask |= (1 << c);
}

void addChild(int v, int ans, int pos, int len)
{
	tree[v].go[str[pos] ] = ans;
	tree[ans] = Node(v, pos, len);
}

int split(int v, int down)
{
	if (down == tree[v].len)
		return v;
	if (down == 0)
		return tree[v].par;
	int ans = sz++;
	addChild(tree[v].par, ans, tree[v].pos, down);
	tree[v].pos += down;
	tree[v].len -= down;
	tree[v].par = ans;
	tree[ans].go[str[tree[v].pos] ] = v;
	return ans;
}


int st[maxn];
int sp; 

void addChar(int &v, int i, int n)
{
	int len = n - i;
	sp = 0;
	int c = str[i];
	while (bit(tree[v].linkMask, c) == 0)
	{
		len -= tree[v].len;
		st[sp++] = v;
		v = tree[v].par;
	}
	int w = tree[v].link[c];
	if (tree[w].go.count(str[i + len] ) != 0)
	{
		int u = tree[w].go[str[i + len] ];
		int pos = tree[u].pos;
		
		while (str[pos] == str[i + len] )
		{
			int curlen = tree[st[sp - 1] ].len;
			len += curlen;
			pos += curlen;
			sp--;
		}

		w = split(u, pos - tree[u].pos);
		addLink(st[sp], w, c);
	}
	v = sz++;
	addChild(w, v, i + len, n - (i + len) );
}

void printTree(int v, string s = "")
{
	eprintf("%2d:%s", v, s.c_str() );
	if (v != 1)
	{
		for (int i = 0; i < tree[v].len; i++)
		{
			eprintf("%c", str[tree[v].pos + i] + 'a');
			s += " ";
		}
	}
	eprintf("\n");

	for (auto it : tree[v].go)
	{
		printTree(it.second, s);
	}
}

int main()
{
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
#endif
	init();

	scanf("%s", str);
	int n = strlen(str);
	for (int i = 0; i < n; i++)
	{
		str[i] -= 'a';
	}
	str[n++] = 26;
	int v = root;
	for (int i = n - 1; i >= 0; i--)
	{
		addChar(v, i, n);
//		eprintf("i = %d\n", i);
//		printTree(1);
//		eprintf("\n");
	}
	int ans = 0;
	for (int i = 2; i < sz; i++)
	{
		ans += tree[i].len;
		if (tree[i].pos + tree[i].len == n)
			ans--;
	}
	printf("%d\n", ans);

	return 0;
}



